package com.example.blog_system.controller;

import com.example.blog_system.common.AjaxResult;
import com.example.blog_system.common.AppVariable;
import com.example.blog_system.entity.ArticleInfo;
import com.example.blog_system.entity.CommentInfo;
import com.example.blog_system.entity.UserInfo;
import com.example.blog_system.entity.vo.ArticleInfoVO;
import com.example.blog_system.entity.vo.CommentInfoVO;
import com.example.blog_system.entity.vo.UserInfoVO;
import com.example.blog_system.enums.SortOption;
import com.example.blog_system.service.ArticleService;
import com.example.blog_system.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpSession;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.*;

/**
 * Created with IntelliJ IDEA.
 * Description: 文章控制层
 */
@RestController
@Slf4j
@RequestMapping("article")
public class ArticleController {

    @Autowired
    private ArticleService articleService;

    @Autowired
    private UserService userService;


    /**11
     * 将当前用户所有博文 (草稿或者已发布) 截断返回
     *
     * @param userInfo
     * @return
     */
    @RequestMapping("/showuserarticles")
    public AjaxResult showArticleInfo(@SessionAttribute(AppVariable.USER_SESSION_KEY) UserInfo userInfo ,Integer state) {
//检验参数
        if(userInfo.getState()==0)return AjaxResult.fail(-1, "请注册后再访问个人主页~");
        if(state==null||!(state==1||state==2)){
            return AjaxResult.fail(-1, "参数异常!");
        }
        Integer userId = userInfo.getId();
        List<ArticleInfoVO> articleInfoVOList = articleService.showArticleInfo(userId,state);
//        for (ArticleInfoVO a : articleInfoVOList) {
//            // 正文长度如果超过100则 截断
//            if (a.getContent().length() >= 100) {
//                a.setContent(a.getContent().substring(0,101)+"......(浏览文章详情,请点击查看全文)");
//
//            }
//            a.setContent(a.getContent().replaceAll("[*#=%]", "")); // 将截断内容出现的特殊字符消除
//
//        }
        if(state==2)
        articleService.log(userInfo.getUsername(),"查看未发布的文章");
        else if(state==1)
            articleService.log(userInfo.getUsername(),"查看已发布的文章");
        return AjaxResult.success(200, articleInfoVOList);

    }
    /**1
     * 用户删除文章
     * @param userInfo
     * @param id
     * @param state
     * @return
     */
    @RequestMapping("/del")
    @Transactional
    public AjaxResult del(@SessionAttribute(AppVariable.USER_SESSION_KEY) UserInfo userInfo, Integer id,Integer state) throws Exception {
        if(userInfo.getState()==0)return AjaxResult.success(-1,"非法操作");
        //  验证 删除博文的id有效性
        if (id == null || id < 1 ||state==null||! (state==1||state==2)) {
            return AjaxResult.fail(-1, "非法参数!");
        }
        Integer uid = userInfo.getId();
        Integer len = articleService.del(uid, id,state); // 删除 当前用户对应的此博文id  的博文
        if(len == 0 ){
            return AjaxResult.success(1, "删除博文失败", len);
        }

//        获取文章获赞数
        Integer likeNum=articleService.getLikeNum(uid,id);

//        区分 删除草稿和文章  state 1是文章 2是草稿
//        删除已发布文章 还要减博文数
        if(state==1){
//            当前用户的文章数-1
            Integer bLen = userService.delBCount(userInfo.getId());
            if(bLen==0)throw new Exception("删除文章数失败!");

//            // 删除点赞表里所有用户对此博文的点赞 可能没有
//            articleService.delLikeInfo(id);

//            if(bLen==0)throw new Exception("删除失败!");
            // 删除用户表里 作者对应的获赞量
            userService.delAuthorLiked(id,likeNum);

            // 更新了数据库的用户博文数量 还要更新一下当前session里的用户博文数量
            userInfo.setBlogCount(userInfo.getBlogCount() - 1);
            //更新用户获赞量
            userInfo.setLiked(userInfo.getLiked()-likeNum);
            articleService.log(userInfo.getUsername(),"删除博文-> bid :"+id);
        }else if(state==2){
            articleService.log(userInfo.getUsername(),"删除草稿-> bid :"+id);
        }



        return AjaxResult.success(200, len);
    }

    /**1
     *  管理员删除文章
     *
     * @param user
     * @param id
     * @param state
     * @return
     */
    @RequestMapping("/delbyadmin")
    @Transactional
    public AjaxResult delByAdmin(@SessionAttribute(AppVariable.USER_SESSION_KEY) UserInfo user, Integer id,Integer state) throws Exception {
        if(user.getState()!=2)return AjaxResult.success(-1,"非法操作");

        //  验证 删除博文的id有效性 博文的状态
        if (id == null || id < 1 ||state==null||! (state==1||state==2)) {
            return AjaxResult.fail(-1, "非法参数!");
        }

//         先根据博文id找到其作者id
        Integer uid=articleService.getUidById(id);

        if(uid==null||uid<1){
            return AjaxResult.fail(1, "删除文章失败");
        }
//        逻辑删除博文
        Integer len = articleService.delByAdmin( id,state);

        if(len == 0 ){
            return AjaxResult.success(1, "删除失败,文章不存在或已被删除!", len);
        }



//       对应作者博文量-1
            Integer bLen = userService.delBCount(uid);
        if(bLen==0)throw  new Exception("删除博文数失败!");

//        // 删除点赞表里所有用户对此博文的点赞  保留点赞
//        articleService.delLikeInfo(id);
//        if ( bLen == 0) {
//            return AjaxResult.success(1, "删除失败", bLen);
//        }


//        // 删除文章对应的获赞量
//        bLen =articleService.delLike(id,likedNum);
//        if ( bLen == 0) {
//            return AjaxResult.success(1, "删除失败", bLen);
//        }
        //获得作者此篇文章的获赞量
        Integer likeNum=articleService.getLikeNum(uid,id);

        //删除作者获赞量 关于此篇文章 可能没有
        if(likeNum!=0)
         userService.delAuthorLiked(uid,likeNum);



            if(Objects.equals(user.getId(), uid)){// 如果管理员删除的是自己文章 则对应减session里的信息
                user.setLiked(user.getLiked()-likeNum);
                user.setBlogCount(user.getBlogCount()-1);
            }


        articleService.log("管理员","删除博文-> bid :"+id);
        return AjaxResult.success(200, len);
    }

    /**!
     * 查看 当前用户的 指定博文详情页
     *
     * @param id
     * @return
     */
    @Transactional
    @RequestMapping("/showmyarticle")
    public AjaxResult showMyBlog(@SessionAttribute(AppVariable.USER_SESSION_KEY) UserInfo userInfo,
                                 @RequestParam("id") Integer id) {
        if (id == null) {
            return AjaxResult.fail(-1, "参数异常!");
        }

//         检查 是否是当前用户的博文
        ArticleInfoVO articleInfoVO = articleService.showMyArticle(userInfo.getId(), id);
        if (articleInfoVO == null) {
            return AjaxResult.fail(-1, "查找文章操作异常!");
        }
        // 添加阅读量
        articleService.addRCount(articleInfoVO.getId());
        articleService.log(userInfo.getUsername(),"查看博文详情-> bid :"+id);
        return AjaxResult.success(200, articleInfoVO);
    }


    /**1
     * 给当前用户添加博文
     *
     * @param userInfo
     * @param text
     * @return
     */
    @RequestMapping("/add")
    @Transactional
    public AjaxResult add(@SessionAttribute(AppVariable.USER_SESSION_KEY) UserInfo userInfo,
                          @RequestBody ArticleInfo text) throws Exception {
        // 参数有效性校验
        if(userInfo.getState()==0)return AjaxResult.success(-1,"非法操作");
        if (!StringUtils.hasLength(text.getTitle())
                || !StringUtils.hasLength(text.getContent())
                ||!StringUtils.hasLength(text.getDescription())
                ||text.getState()==null
                ||!(text.getState()==1
                ||text.getState()==2)) {
            return AjaxResult.fail(-1, "非法参数!");
        }

        if(text.getTitle().length()>25){
            return AjaxResult.fail(-1, "文章标题不得超过25字符!");
        }

        // 添加上作者id  当前发布和更新时间
        text.setUid(userInfo.getId());
        text.setCreatetime(LocalDateTime.now());
        text.setUpdatetime(LocalDateTime.now());

        ArticleInfoVO articleInfo=new ArticleInfoVO();

        int option=0;

//        如果状态为2 则是将草稿发布  此时即修改草稿状态
        if(text.getState()==2){
            text.setState(1);

            //    将文章的一些属性 深拷贝到 文章视图对象 用于修改草稿
            BeanUtils.copyProperties(text,articleInfo);
             option=articleService.modify(userInfo.getId(),articleInfo);

            articleService.log(userInfo.getUsername(),"将待发布博文发布-> title :"+text.getTitle());
        }



//        如果没有修改记录 则是新增博文
        if(option==0){
             int len = articleService.add(text);
//        状态为1 是发文 则 添加博文数
            if (len == 0  ) {
                throw new Exception("添加博文失败!");
            }

            articleService.log(userInfo.getUsername(),"发布新博文-> title :"+text.getTitle());

        }

        //更新博文数量
        int bLen = userService.addBCount(userInfo.getId());
        if(bLen == 0){
             throw new Exception("添加博文数量失败!");
        }
        // 更新了数据库的用户博文数量 还要更新一下当前session里的用户博文数量
        userInfo.setBlogCount(userInfo.getBlogCount() + 1);



        return AjaxResult.success(200, 1);
    }

    /**!
     * 将文章保存在草稿箱
     * @param userInfo
     * @param tmpArticle
     * @return
     */
    @RequestMapping("/save")
    public AjaxResult save(@SessionAttribute(AppVariable.USER_SESSION_KEY)UserInfo userInfo,@RequestBody ArticleInfo tmpArticle) throws Exception {
        if(userInfo.getState()==0)return AjaxResult.success(-1,"非法操作");

//         草稿文章参数校验
        if(!StringUtils.hasLength(tmpArticle.getTitle())
                ||!StringUtils.hasLength(tmpArticle.getContent())
                ||!StringUtils.hasLength(tmpArticle.getDescription())
                ||tmpArticle.getState()==null
                ||tmpArticle.getState()!=2){
            return AjaxResult.fail(-1, "参数异常!");
        }
        // 添加上作者id  当前发布和更新时间
        tmpArticle.setUid(userInfo.getId());
        tmpArticle.setCreatetime(LocalDateTime.now());
        tmpArticle.setUpdatetime(LocalDateTime.now());
        Integer len=articleService.save(userInfo.getId(),tmpArticle);

        if(len==0){
            throw new Exception("文章保存失败");
        }

        articleService.log(userInfo.getUsername(),"暂存博文-> title :"+tmpArticle.getTitle());
        return AjaxResult.success(200,len);
    }

    /** 1
     * 用于修改界面 根据id获取当前用户的 博文标题和正文
     *
     * @param userInfo
     * @param id
     * @return
     */
    @RequestMapping("/getblog")
    public AjaxResult getBlogToModify(@SessionAttribute(AppVariable.USER_SESSION_KEY) UserInfo userInfo, Integer id) {
        if(userInfo.getState()==0)return AjaxResult.success(-1,"非法操作");

        //参数校验
        if (id == null || id < 1) {
            return AjaxResult.fail(-1, "非法参数!");
        }
        Integer uid = userInfo.getId();
        ArticleInfoVO article = articleService.getBlog(uid, id);

        return AjaxResult.success(200, article);
    }


    /**1
     * 修改博文操作 指定博文id 给其对应的用户id 的博文进行修改
     *  修改 已发布文章或者修改草稿文章 根据是否传入state字段
     * @param userInfo
     * @param articleInfoVO
     * @return
     */
    @RequestMapping("/modify")
    public AjaxResult modify(@SessionAttribute(AppVariable.USER_SESSION_KEY) UserInfo userInfo, @RequestBody ArticleInfoVO articleInfoVO) throws Exception {
        if(userInfo.getState()==0)return AjaxResult.success(-1,"非法操作");

        //参数校验  id不能为空或者小于1 状态码不能为空或者 非 发布非 草稿
        if (articleInfoVO.getId() == null || articleInfoVO.getId() < 1) {
            return AjaxResult.fail(-1, "非法参数!");
        }
        if(articleInfoVO.getState()!=null&&articleInfoVO.getState()!=2 ){
             return AjaxResult.fail(-1, "非法参数!");
        }
        if(!StringUtils.hasLength(articleInfoVO.getTitle())
                ||!StringUtils.hasLength(articleInfoVO.getDescription())
                ||!StringUtils.hasLength(articleInfoVO.getContent())){
            return AjaxResult.fail(-1, "非法参数");
        }
        Integer uid = userInfo.getId();
        // 更新当前修改时间
        articleInfoVO.setUpdatetime(LocalDateTime.now());
        // 根据 uid 和 id 去找博文 去修改 标题 正文 和更新时间
        Integer len=articleService.modify(uid, articleInfoVO);
            if (len == 0) {
                throw new Exception("文章修改失败!");
            }
            if(articleInfoVO.getState() ==null){
                articleService.log(userInfo.getUsername(),"修改已发布博文-> title :"+articleInfoVO.getTitle());
            }else if(articleInfoVO.getState() ==2){
                articleService.log(userInfo.getUsername(),"修改未发布博文-> title :"+articleInfoVO.getTitle());
            }
        return AjaxResult.success(200, len);

    }

    /**1
     * 分页查询博文
     *
     * @param pindex
     * @param psize
     * @return
     */
    @RequestMapping("/showblogs")
    @Transactional
    public AjaxResult showBlogsByPage(@SessionAttribute(AppVariable.USER_SESSION_KEY) UserInfo userInfo,Integer pindex, Integer psize,Integer sortoption) {

        // pindex 和psize 可以接收 url的querystring 和通过form表单 发送的 body正文的querystring  不能接收json格式的 querystring和json

        // 检验参数 页面下标 非法时置为1
        if (pindex == null || pindex < 1) {
            pindex = 1;
        }
        // 每页最大显示博文数 非法或者大于3时 置为3  即最多一次显示3条数据
        if (psize == null || psize > 3) {
            psize = 3;
        }


        // 根据页码 和每页显示的数量 计算出 数据库中offset偏移量值
        //  1 3 -> 0   2 3  -> 3  3 3  -> 6
        Integer offset = (pindex - 1) * psize;  // 当前页码减1 乘 页最大博文量 得到 操作数据库的offset偏移量
        String sortvalue;
        String sort  ;
//        SortOption sortOption=SortOption.COLLECTCOUNT_DESC;
        switch (sortoption){
            case 1:sort="desc";sortvalue="updatetime";break;
            case 2:sort="asc";sortvalue="updatetime";break;
            case 3:sort="desc";sortvalue="rcount";break;
            case 4:sort="asc";sortvalue="rcount";break;
            case 5:sort="desc";sortvalue="likedcount";break;
            case 6:sort="asc";sortvalue="likedcount";break;
            case 7:sort="desc";sortvalue="commentcount";break;
            case 8:sort="asc";sortvalue="commentcount";break;
            case 9:sort="desc";sortvalue="collection_count";break;
            case 10:sort="asc";sortvalue="collection_count";break;
            default:sort="desc";sortvalue="heat";break;
        }


        List<ArticleInfoVO> articleInfoVOS = articleService.showBlogsByPage(offset, psize,sort,sortvalue );
        // 列表文章 最多显示100字
        if(articleInfoVOS.isEmpty()){
            return null;
        }
        //Integer maxHeat=articleInfoVOS.get(0).getHeat();

        for (int i=0; i<articleInfoVOS.size();i++) {
            ArticleInfoVO article=articleInfoVOS.get(i);
            article.setUsername(userService.getUsernameById(article.getUid()));
            //article.setContent(article.getContent().replaceAll("[*#=%]", "")); // 将截断内容出现的特殊字符消除

//            if (article.getContent().length() > 100){
//                article.setContent(article.getContent().substring(0,101)+"......(浏览文章详情,请点击查看全文)");
//            }

//            if(sortvalue.equals("heat")){
//                Long timeNum = article.getUpdatetime().toInstant(ZoneOffset.of("+8")).toEpochMilli();
//                if(timeNum-System.currentTimeMillis()<3*60*60*1000){
//                    article.setHeat(maxHeat+400);
//                    articleInfoVOS.remove(article);
//                    articleInfoVOS.add(0,article);
//                }else if(timeNum-System.currentTimeMillis()<6*60*60*1000){
//                    article.setHeat(maxHeat+300);
//                    articleInfoVOS.remove(article);
//                    (articleInfoVOS).add(0,article);
//                }else if(timeNum-System.currentTimeMillis()<12*60*60*1000){
//                    article.setHeat(maxHeat+200);
//                    articleInfoVOS.remove(article);
//                    articleInfoVOS.add(0,article);
//                }else if(timeNum-System.currentTimeMillis()<24*60*60*1000){
//                    article.setHeat(maxHeat+100);
//                    articleInfoVOS.remove(article);
//                    articleInfoVOS.add(0,article);
//                }
//                i--;
//            }

        }

        userService.log(userInfo.getUsername(),"分页浏览全部文章: -> sort:"+sort+" sortvalue:"+sortvalue);

        return AjaxResult.success(200, articleInfoVOS);
    }

    /**1
     * 获取 所有博文数量 返回最大页数
     *
     * @return
     */
    @RequestMapping("/getpagemax")
    public AjaxResult getBlogCount(Integer psize) {
        int blogCount = articleService.getBlogCount();
//        按当前一次显示多少页 去计算博文最大页数
        //Math.ceil(); 判断浮点数 如果不是整数则向上取整
        //  判断当前 博文数量 是否能整除 每页的页数 能则有对应的数量  不能则额外加一页显示多出来的博文
        return AjaxResult.success(200, blogCount % psize == 0 ? blogCount / psize : blogCount / psize + 1);
    }

    /**1
     * 查看全文(公共博文)
     * 根据博文id查找对应的博文 (不用对应用户id)
     *
     * @param id
     * @return
     */
    @RequestMapping("/getcontent")
    public AjaxResult getContent(@SessionAttribute(AppVariable.USER_SESSION_KEY) UserInfo userInfo,Integer id) {
        if (id == null || id < 1) {
            return AjaxResult.fail(-1, "参数异常!");
        }

        ArticleInfoVO articleInfoVO = articleService.getContent(id);
        if (articleInfoVO == null) {
            return AjaxResult.success(-1, "查询失败", null);
        }

//        查找的文章阅读量+1
        articleService.addRCount(id);
        if(userInfo.getState()==0){
            articleInfoVO.setContent(articleInfoVO.getContent().substring(0,articleInfoVO.getContent().length()/3)+
                    "......\n\n\n\n-----------------------------成为注册用户即可查看文章全部内容----------------------------");
        }

        articleService.log(userInfo.getUsername(),"查看此篇公共博文-> bid :"+id);
        return AjaxResult.success(200, articleInfoVO);
    }

    /**
     * 显示 收藏的博文
     * @param userInfo
     * @return
     */
    @RequestMapping("/showblogsbycollect")
    public AjaxResult showBlogsByCollection(@SessionAttribute(AppVariable.USER_SESSION_KEY) UserInfo userInfo){
        List<ArticleInfoVO> articleInfoVOS = articleService.showBlogsByCollection(userInfo.getId());
        for(ArticleInfoVO article: articleInfoVOS){
                // 根据博文id得到用户名 设置到博文列表里
                article.setUsername(userService.getUsernameById(article.getUid()));;
//                if (article.getContent().length() > 100)
//                    article.setContent(article.getContent().substring(0, 100)+"...");
//                article.setContent(article.getContent().replaceAll("[*#=%]", "")); // 将截断内容出现的特殊字符消除
        }

        articleService.log(userInfo.getUsername(),"查看收藏的所有博文");
        return AjaxResult.success(200, articleInfoVOS);
    }
    /**1
     * 显示当前博文 是否被当前用户点赞
     *
     * @param userInfo
     * @param id
     * @return
     */
    @RequestMapping("/showlike")
    public AjaxResult likeInfo(@SessionAttribute(AppVariable.USER_SESSION_KEY) UserInfo userInfo, Integer id) {
        if (id == null || id < 1) {
            return AjaxResult.fail(-1, "参数异常");
        }
        Integer uid = articleService.linkInfo(userInfo.getId(), id);

        return AjaxResult.success(200, uid);
    }


    /**1
     * 点赞 或取消点赞  包含 给用户获赞+1 -1   包含给点赞文章获赞+1 -1
     *
     * @param userInfo
     * @param id
     * @return
     */
    @RequestMapping("/like")
    @Transactional
    public AjaxResult like(@SessionAttribute(AppVariable.USER_SESSION_KEY) UserInfo userInfo, Integer id) throws Exception {
        if(userInfo.getState()==0)return AjaxResult.fail(-1, "游客不能点赞博文~");
        if (id == null || id < 1) {
            return AjaxResult.fail(-1, "参数异常!");
        }
        Integer uid = userInfo.getId();

        // 获取 是否点赞   为null 即没有点赞信息
        Integer likeInfo = articleService.linkInfo(uid, id);

        // 查找作者信息
        UserInfoVO author = userService.getAuthor(id);


        HashMap<String, Object> map = new HashMap<>();
        // 将作者名放到map里
        map.put("username", author.getUsername());
        //  点赞 当前用户给 对应博文点赞   对应博文的作者获赞数+1
        if (likeInfo == null) {
            Integer optionLen;
            Integer optionLen1;
            Integer optionLen2;
            optionLen = articleService.like(uid, id);
            //给作者获赞数+1
            optionLen1 = userService.addLike(author.getId());
            //给博文获赞数+1  (已发布的博文)
            optionLen2 = articleService.addLike(id);

            if (optionLen == 0 || optionLen1 == 0 || optionLen2 == 0) { //  有操作为0 则抛出异常回滚
                throw new Exception("操作失败!");

            }

            // 如果作者是当前用户 给session中的点赞信息+1
            if (userInfo.getUsername().equals(author.getUsername())) {
                userInfo.setLiked(userInfo.getLiked() + 1);
            }
//            记录当前点赞操作
            map.put("like", true);
            articleService.log(userInfo.getUsername(),"点赞博文-> bid :"+id);

        } else {  // 取消点赞  删除点赞记录 给对应作者获赞数-1  给对应博文获赞数-1
            Integer optionLen;
            Integer optionLen1;
            Integer optionLen2;
            optionLen = articleService.unlike(uid, id);
            // 作者获赞数-1
            optionLen1 = userService.delAuthorLiked(author.getId(),1);
            // 博文获赞数-1
            optionLen2 = articleService.delLike(id,1);
            if (optionLen == 0 || optionLen1 == 0 || optionLen2 == 0) {//  有操作为0 则抛出异常回滚
                throw new Exception("操作失败!");
            }
            // 如果作者是当前用户 给session中的点赞信息-1
            if (userInfo.getUsername().equals(author.getUsername())) {
                userInfo.setLiked(userInfo.getLiked() - 1);
            }
//            当前取消点赞操作
            map.put("like", false);
            articleService.log(userInfo.getUsername(),"取消点赞博文-> bid :"+id);
        }
        return AjaxResult.success(200, map);
    }

    /**
     *  收藏博文  , 取消收藏博文   附加 对文章收藏数 +1 -1  针对的是已发布的博文
     * @param userInfo
     * @param bid
     * @return
     * @throws Exception
     */
    @Transactional
    @RequestMapping("/collect")
    public AjaxResult collect(@SessionAttribute(AppVariable.USER_SESSION_KEY) UserInfo userInfo,@RequestParam("id") Integer bid) throws Exception {
        if(userInfo.getState()==0)return AjaxResult.fail(-1,"游客不能收藏博文~");
        if(bid==null||bid<1){
            return AjaxResult.fail(-1, "参数有误!");
        }
        Integer uid=userInfo.getId();
//         检验博文是否被收藏
        Integer ret=articleService.collectInfo(uid, bid);
        HashMap<String,Object> hashMap = new HashMap<>();
        hashMap.put("username",userInfo.getUsername() );
        if(ret==null){
//            收藏操作
            Integer len1=articleService.collect(uid, bid);
            //给当前博文收藏数+1  (已发布的博文)
            Integer len2=articleService.addCollectionCount(bid);
            if(len1==0||len2==0){ // 收藏的两个操作 有影响行数为0则抛出异常回滚
                throw new Exception("收藏操作失败!");
            }
//             已收藏
            hashMap.put("collect", true);

            articleService.log(userInfo.getUsername(),"收藏博文-> bid :"+bid);
        }else{
            //  取消收藏操作
            Integer len1=articleService.uncollect(uid,bid);
//             博文收藏数-1 (同时检验是否取消收藏的是已发布博文)
            Integer len2=articleService.delCollectionCount(bid);
            if(len1==0||len2==0){ // 收藏的两个操作 有影响行数为0则抛出异常回滚
                throw new Exception("取消收藏操作失败!");
            }
            // 已取消收藏
            hashMap.put("collect", false);
            articleService.log(userInfo.getUsername(),"取消收藏博文-> bid :"+bid);
        }
        return AjaxResult.success(200, hashMap);
    }

    /**1
     * 显示当前博文 是否被当前用户点赞
     *
     * @param userInfo
     * @param bid
     * @return
     */

    @RequestMapping("/collectinfo")
    public AjaxResult collectInfo(@SessionAttribute(AppVariable.USER_SESSION_KEY) UserInfo userInfo, @RequestParam("id") Integer bid) {
        if (bid == null || bid < 1) {
            return AjaxResult.fail(-1, "参数异常");
        }
        Integer uid = articleService.collectInfo(userInfo.getId(), bid);
        return AjaxResult.success(200, uid);
    }

    /**1
     *  查找指定标题的文章返回 模糊查找
     * @param title
     * @return
     */
    @RequestMapping("/search")
    public AjaxResult searchArticle(@SessionAttribute(AppVariable.USER_SESSION_KEY) UserInfo userInfo, String option ,String title){
        //参数校验
        if((!StringUtils.hasLength(title))||(!StringUtils.hasLength(option))){
            return AjaxResult.fail(-1,"参数有误!");
        }
        if(!(option.equals("title")||option.equals("username"))){
            return AjaxResult.fail(-1, "非法选项!");
        }
        List<ArticleInfoVO> list =  articleService.searchArticle(option,title);
        // 列表文章 最多显示100字
        for (ArticleInfoVO article : list) {
            // 根据博文id得到用户名 设置到博文列表里
            article.setUsername(userService.getUsernameById(article.getUid()));;
//            if (article.getContent().length() > 100)
//                article.setContent(article.getContent().substring(0, 100)+"...");
//            article.setContent(article.getContent().replaceAll("[*#=%]", "")); // 将截断内容出现的特殊字符消除
        }

        articleService.log(userInfo.getUsername(),"检索博文->  检索选项:"+option+" 检索内容:"+title);
        return AjaxResult.success(200,list);
    }

    /**
     *  根据作者 id 返回作者所有博文列表(简略).
     * @param id
     * @return
     */
    @RequestMapping("/showauthorblogs")
    public AjaxResult showAuthorArticle(@SessionAttribute(AppVariable.USER_SESSION_KEY) UserInfo userInfo,Integer id){
        if(id==null){
            return AjaxResult.fail(-1, "参数有误");
        }
        List<ArticleInfoVO> articleInfoVOS=articleService.showAuthorArticle(id);
        if(articleInfoVOS==null){
            return AjaxResult.fail(-1,"操作异常");
        }
//        for(ArticleInfoVO articleInfo:articleInfoVOS){
//
//            articleInfo.setContent(articleInfo.getContent().replaceAll("[*#=%]", ""));
//            if(articleInfo.getContent().length()>100)
//            articleInfo.setContent(articleInfo.getContent().substring(0,101)+"......(浏览文章详情,请点击查看全文)");
//        }

        articleService.log(userInfo.getUsername(),"查看当前作者所有博文-> uid :"+id);
        return  AjaxResult.success(200, articleInfoVOS);
    }

    /**
     *  返回当前博文的所有评论信息 (日期降序排序)
     * @param id   接受前端的博文id
     * @return  评论id 评论人 日期 信息 是否可删除的状态
     */

    @RequestMapping("/showComments")
    public AjaxResult showComments(@SessionAttribute(AppVariable.USER_SESSION_KEY) UserInfo userInfo,Integer id,String name){
        //  当前用户 名字 和评论信息的名字相同 当前用户和 博文作者名称相同 状态码为2的管理员(可删除)
        if(id ==null||id<1||!StringUtils.hasLength(name)){
            return AjaxResult.fail(-1, "非法参数!");
        }
//        log.info("评论人:"+name);
        List<CommentInfoVO> comments = articleService.showComments(id);
        for(CommentInfoVO comment:comments){
//             管理员 || 作者 || 评论者 都可以删除当前评论
            if(userInfo.getState()==2||name.equals(userInfo.getUsername())
                    ||userInfo.getUsername().equals(comment.getUsername())){
                comment.setIsdel(true);
            }
        }


        return AjaxResult.success(200,comments);
    }

    /**
     *  添加评论
     * @param userInfo 当前登录用户
     * @param commentInfo 拿到的 评论信息 (博文id 评论内容)
     * @return 返回 当前评论id 评论日期  评论人
     */
    @RequestMapping("/addcomment")
    @Transactional
    public AjaxResult addComment(@SessionAttribute(AppVariable.USER_SESSION_KEY) UserInfo userInfo, @RequestBody CommentInfo commentInfo, HttpSession httpSession){
        if(userInfo.getState()==0)return AjaxResult.fail(-1,"游客不能发送评论~");
        if(commentInfo==null||commentInfo.getBid()==null||commentInfo.getBid()<1||
                !StringUtils.hasLength(commentInfo.getMessage()) ){
            return AjaxResult.fail(-1,"非法参数!");
        }

        if(commentInfo.getMessage().length()>100){
            return AjaxResult.fail(-1, "评论内容不得超过100字符!");
        }


        CommentInfoVO commentInfoVO=new CommentInfoVO();
        Integer uid=userInfo.getId();
        LocalDateTime nowTime=LocalDateTime.now(); // 当前日期
        commentInfo.setUid(uid); // 当前用户id
        commentInfo.setTime(nowTime);
        Integer count=(Integer) httpSession.getAttribute("commentcount");
        if(count!=null&&count>5){  // 当发送的评论超过五条后 发送评论的间隔不能超过五秒!
            if(httpSession.getAttribute("commentTime")!=null
                    &&(System.currentTimeMillis()-(long)httpSession.getAttribute("commentTime")<10_000)){
                httpSession.setAttribute("commentTime",System.currentTimeMillis());
                return AjaxResult.fail(-1, "评论太快了,请休息一下再评论吧~");
            }else{
//                 间隔五秒后允许发送两条评论
                httpSession.setAttribute("commentcount",count-2);
            }
        }


            Integer len=articleService.addComment(commentInfo);  // 添加评论 同时 将自增id的值 给 commentInfo对象
        if(len==1){
            // 添加成功  将当前评论id 评论日期  评论人 传给前端
            BeanUtils.copyProperties(commentInfo, commentInfoVO);
            commentInfoVO.setUsername(userInfo.getUsername());
//            Map<String,Object> data=new HashMap<>();
//            data.put("time", commentInfo.getTime());
//            data.put("name", userInfo.getUsername());
//            data.put("cid", commentInfo.getCid());
//             给文章添加评论数
            articleService.addCommentCount(commentInfo.getBid());

            if(count==null){
                httpSession.setAttribute("commentcount",1);
            }else{
                httpSession.setAttribute("commentcount",count+1);
            }
            httpSession.setAttribute("commentTime",System.currentTimeMillis());


            articleService.log(userInfo.getUsername(),"发送评论 用户-> uid: "+commentInfo.getUid()+" 博文-> bid:"+ commentInfo.getBid()+"添加评论-> cid: "+commentInfo.getCid());
            return AjaxResult.success(200,commentInfoVO);
        }

        else
            return AjaxResult.fail(-1, "评论失败!");
    }

    /**
     *  删除评论
     * @param cid  评论id
     * @return
     */

    @Transactional
    @RequestMapping("/delcomment")
    public AjaxResult delComment(@SessionAttribute(AppVariable.USER_SESSION_KEY) UserInfo userInfo, Integer id,Integer cid,String name){
        if(userInfo.getState()==0)return AjaxResult.success(-1,"非法操作");

        //有效性校验
        if(cid==null||cid<1||id==null||id<1){
            return AjaxResult.fail(-1, "参数有误!");
        }

//         查找此条评论
        Integer uid= articleService.getUidByCid(cid);
        if(uid==null){
            return  AjaxResult.fail(-1, "当前评论不存在或已被删除!");
        }
//        log.info("state:"+userInfo.getState()+" username:"+userInfo.getUsername()+" name:"+name+" cid:"+cid
//                +"id:"+id+"uid:"+uid);
        //  检验当前是否可以删除   管理员可以 当前作者可以 评论者可以
        if(!(userInfo.getState()==2||name.equals(userInfo.getUsername())
                ||userInfo.getId().equals(uid))){
            return AjaxResult.fail(-1, "删除失败!");
        }

        Integer len=articleService.delComment(id,cid);
        if(len==1){
            articleService.delCommentCount(cid);
            articleService.log(userInfo.getUsername(),"删除评论-> cid :"+cid);
            return AjaxResult.success(200, len);
        }else{
            return AjaxResult.fail(-1, "删除失败!");
        }
    }
}
